# build in python3.5.2
# 作者：陈常鸿
# 用方差求得距离，再查看哪个最近，最后累加label
# 这里用operator可以配合sorted()根据某个键值来排序，itemgetter(1)就是第二个值
# 字典dict.items()，items() 函数以列表返回可遍历的(键, 值) 元组数组
import math
import operator as op

a=[1,2,3,3,2,1,'a']
b=[7,8,9,9,8,7,'b']
c=[1,1,1,1,1,1]
# 平方差,计算出两个样本之间的距离
def euclieanDistance(instance1,instance2,lengh):
    distance=0
    for i in range(lengh):
        distance+=pow(instance1[i]-instance2[i],2)
    return math.sqrt(distance)

# 根据距离，找到最近的那堆数据
def getNeighbors(trainSet,testInstance,k):
    distance=[]
    lengh=len(testInstance)            # 减去label项
    for i in range(len(trainSet)):
        dist=euclieanDistance(testInstance,trainSet[i],lengh)
        distance.append((trainSet[i],dist))
    distance.sort(key=op.itemgetter(1))    # 按照第二个选项排序 ，从小到大
    neighbor=[]
    for j in range(k):
        neighbor.append(distance[j][0])
    return neighbor

# 查看最近的数据是哪个标签，靠近的标签排序
def getResponse(neighbor):
    classVote={}
    for i in range(len(neighbor)):
        response=neighbor[i][-1]         # 把label选出来,所以response是标签
        if response in classVote:
            classVote[response]+=1
        else:
            classVote[response]=1
    sortVote=sorted(classVote.items(),key=op.itemgetter(1),reverse=True)  # itemgetter(1)根据字典第二个值来排序，
    return sortVote[0][0]

# 求准确度，相当于预测
def getAccuracy(testSet,predictions):
    correct=0
    for i in range(len(testSet)):
        if testSet[i][-1] is predictions[i]:
            correct+=1
    return (correct/float(len(testSet)))*100.0


if __name__=='__main__':
    predictions=[]
    neighbor=getNeighbors([a,b],c,2)
    print('neighbor',neighbor)
    response=getResponse(neighbor)
    print('response',response)
    predictions.append(response)
    print('predictions',predictions)
    print(getAccuracy([[6,6,6,6,6,6,'b']],predictions))

#print(getAccuracy([[1, 2, 3, 3, 2, 1, 'a'], [7, 8, 9, 9, 8, 7, 'b']],['a','b']))
#print(getNeighbors([a,b],c,2))
#print(euclieanDistance(a,b,6))
